package controllers.games;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

import models.games.LuceRiflessa;
import models.util.Indexes;
import views.games.LuceRiflessaView;
import views.util.GameColors;
import core.GameLauncher;
import core.GameLauncher.State;
import core.constants.Constants;

public class LuceRiflessaController implements ActionListener {

	private LuceRiflessaView view;
	private LuceRiflessa model;
	private Indexes[] slashesPosition;
	// private List<Indexes> alreadyFound = new ArrayList<Indexes>();
	private int round = 1;
	private boolean enabledBorder;
	private final int MAX_ROUNDS = Constants.getRounds();
	private GameLauncher gameLauncher;

	public LuceRiflessaController(LuceRiflessa model, LuceRiflessaView view,
			GameLauncher gameLauncher) {
		this.view = view;
		this.model = model;
		this.gameLauncher = gameLauncher;
		slashesPosition = model.getBouncesArray();
		view.addMouseListenerToTheBorder(new CellActionListener());
		view.addActionListenerToGame(this);
		view.setOther("SBARRETTE " + slashesPosition.length);
		showSlashes(true);
	}

	private void newRound(boolean won, int clickedX, int clickedY) {
		if (won) {
			model.setScore(model.getScore() + (model.getLevel() + 1) * 1000);
			gameLauncher.correctAnswer();
			view.setScore(model.getScore());
		}
		if (round == MAX_ROUNDS) {
			view.gameEnded();
			return;
		}
		// RIMUOVE SLASH dalla View
		for (int k = 0; k < slashesPosition.length; k++) {
			int i = slashesPosition[k].getI();
			int j = slashesPosition[k].getJ();
			view.removeImage(i, j);
		}
		Iterator<Indexes> it = model.getPath().iterator();
		while (it.hasNext()) {
			Indexes tmp = it.next();
			view.setCellColor(tmp.getI(), tmp.getJ(), Color.WHITE);
		}
		view.setCellColor(clickedX, clickedY, Color.WHITE);
		model.refresh();
		round++;
		view.setGameClock(round);
		slashesPosition = model.getBouncesArray();
		view.setOther("SBARRETTE " + slashesPosition.length);
		showSlashes(true);
	}

	private class CellActionListener extends MouseAdapter {

		private void showPath(boolean won, int lastX, int lastY) {
			showSlashes(false);
			SwingWorker sw = new ShowPathWorker(won, lastX, lastY);
			sw.execute();
		}

		@Override
		public void mouseClicked(MouseEvent e) {
			if (!enabledBorder)
				return;
			// ///////
			int rowI = model.getCurrentRow();
			int rowJ = model.getCurrentColumn();
			view.removeImage(rowI, rowJ);
			// ///////////
			JLabel target = (JLabel) e.getSource();
			int i = Integer.parseInt("" + target.getName().charAt(0));
			int j = Integer.parseInt("" + target.getName().substring(2));// può
																			// essere
																			// a
																			// 2
																			// cifre
			if (model.verify(i, j)) {
				target.setBackground(Color.GREEN);
				showPath(true, i, j);
			} else {
				target.setBackground(Color.RED);
				showPath(false, i, j);
			}
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			if (!enabledBorder)
				return;
			JLabel target = (JLabel) e.getSource();
			target.setBackground(GameColors.GRIGIO_SCURO);
		}

		@Override
		public void mouseExited(MouseEvent e) {
			if (!enabledBorder)
				return;
			JLabel target = (JLabel) e.getSource();
			target.setBackground(Color.WHITE);
		}

	}

	private void showSlashes(boolean temporanely) {
		enabledBorder = false;
		JLabel[][] cells = view.getCells();
		for (int k = 0; k < slashesPosition.length; k++) {
			int i = slashesPosition[k].getI();
			int j = slashesPosition[k].getJ();
			if (model.getValue(i, j) == 1)
				view.drawSlash(i, j);
			else
				view.drawBackSlash(i, j);
		}
		if (temporanely) {
			HideSlashesWorker htw = new HideSlashesWorker(cells);
			htw.execute();
			ShowStartingPointWorker ssp = new ShowStartingPointWorker(htw);
			ssp.execute();
			// HideStartingPointWorker hsp = new HideStartingPointWorker(ssp);
			// hsp.execute();
		}
	}

	private class HideSlashesWorker extends SwingWorker<Void, Void> {

		private JLabel[][] cells;

		public HideSlashesWorker(JLabel[][] cells) {
			this.cells = cells;
		}

		@Override
		protected Void doInBackground() throws Exception {
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return null;
		}

		public void done() {
			for (int k = 0; k < slashesPosition.length; k++) {
				int i = slashesPosition[k].getI();
				int j = slashesPosition[k].getJ();
				view.removeImage(i, j);
			}
			// enableAll(cells);
		}

	}

	private class ShowOneTileOfThePathWorker extends SwingWorker<Void, Void> {

		private int i, j;

		public int getI() {
			return i;
		}

		public int getJ() {
			return j;
		}

		public ShowOneTileOfThePathWorker(int i, int j) {
			this.i = i;
			this.j = j;
		}

		@Override
		protected Void doInBackground() throws Exception {
			try {
				TimeUnit.MILLISECONDS.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return null;
		}

		public void done() {
			view.setCellColor(i, j, Color.ORANGE);
		}

	}

	private class ShowPathWorker extends SwingWorker<Void, Void> {

		private boolean won;
		private int x, y;

		public ShowPathWorker(boolean won, int x, int y) {
			this.won = won;
			this.x = x;
			this.y = y;
		}

		@Override
		protected Void doInBackground() {
			Iterator<Indexes> it = model.getPath().iterator();
			ShowOneTileOfThePathWorker sw;
			while (it.hasNext()) {
				Indexes tmp = it.next();
				sw = new ShowOneTileOfThePathWorker(tmp.getI(), tmp.getJ());
				sw.execute();
				try {
					sw.get();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (ExecutionException e) {
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return null;
		}

		public void done() {
			newRound(won, x, y);
		}

	}

	private class ShowStartingPointWorker extends SwingWorker<Void, Void> {

		private HideSlashesWorker sw;

		public ShowStartingPointWorker(HideSlashesWorker sw) {
			this.sw = sw;
		}

		@Override
		protected Void doInBackground() throws Exception {
			try {
				sw.get();
				TimeUnit.MILLISECONDS.sleep(250);
				;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return null;
		}

		public void done() {
			int i = model.getCurrentRow();
			int j = model.getCurrentColumn();
			LuceRiflessa.Direction dir = model.getCurrentDirection();
			view.drawStartingDirection(i, j, dir);
			// ////////
			enabledBorder = true;
		}

	}

	// private class HideStartingPointWorker extends SwingWorker<Void, Void> {
	//
	// private ShowStartingPointWorker ssw;
	//
	// public HideStartingPointWorker(ShowStartingPointWorker ssw) {
	// this.ssw = ssw;
	// }
	//
	// @Override
	// protected Void doInBackground() throws Exception {
	// try {
	// ssw.get();
	// TimeUnit.SECONDS.sleep(1);;
	// } catch (InterruptedException e) {
	// e.printStackTrace();
	// }
	// return null;
	// }
	//
	// public void done() {
	// int i = model.getCurrentRow();
	// int j = model.getCurrentColumn();
	// view.removeImage(i, j);
	// enabledBorder = true;//ABILITA IL BORDO DISABILITATO DA SHOWSLASHES()
	// }
	//
	// }

	@Override
	public void actionPerformed(ActionEvent e) {
		JButton source = (JButton) e.getSource();
		String inputText = source.getText();
		if (inputText.equals("Ricomincia")) {
			LuceRiflessa newModel = new LuceRiflessa(model.getCurrentUser());
			LuceRiflessaView newView = new LuceRiflessaView();
			LuceRiflessaController newController = new LuceRiflessaController(
					newModel, newView, gameLauncher);
			gameLauncher.setGame(newModel, newView, newController);
			gameLauncher.startTransition(State.GAME);
			model.addGameToDatabase();
			System.out.println("Ricomincia");
		}

		if (inputText.equals("Menu Giochi")) {
			gameLauncher.startTransition(State.GAME_MENU);
			model.addGameToDatabase();
			System.out.println("Menu Giochi");
		}

	}
}
